/**
 * Copyright (C), 2015-2019, XXX有限公司
 * FileName: NettyServer01
 * Author:   kadibeieun
 * Date:     2019/8/12 14:13
 * Description: 自动绑定递增端口
 * History:
 * <author>          <time>          <version>          <desc>
 * 作者姓名           修改时间           版本号              描述
 */
package 服务端启动流程;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

/**
 * 〈一句话功能简述〉<br> 
 * 〈自动绑定递增端口 〉
 *1. 在上面代码中我们绑定了 8000 端口，接下来我们实现一个稍微复杂一点的逻辑，我们指定一个起始端口号，
 * 比如 1000，然后呢，我们从1000号端口往上找一个端口，直到这个端口能够绑定成功，
 * 比如 1000 端口不可用，我们就尝试绑定 1001，然后 1002，依次类推。
 *
 * 2. serverBootstrap.bind(8000);这个方法呢，它是一个异步的方法，调用之后是立即返回的，
 * 他的返回值是一个ChannelFuture，我们可以给这个ChannelFuture添加一个监听器GenericFutureListener，
 * 然后我们在GenericFutureListener的operationComplete方法里面，我们可以监听端口是否绑定成功，接下来是监测端口是否绑定成功的代码片段
 *
 * @author kadibeieun
 * @create 2019/8/12
 * @since 1.0.0
 */
public class NettyServer01 {
    public static void main(String[] args) {
        NioEventLoopGroup bossgroup = new NioEventLoopGroup();
        NioEventLoopGroup workgroup = new NioEventLoopGroup();

        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap
                .group(bossgroup,workgroup)
                //childOption()可以给每条连接设置一些TCP底层相关的属性，比如上面，我们设置了两种TCP属性，其中

                //ChannelOption.SO_KEEPALIVE表示是否开启TCP底层心跳机制，true为开启
               // .childOption(ChannelOption.SO_KEEPALIVE,true)
                //ChannelOption.TCP_NODELAY表示是否开启Nagle算法，true表示关闭，false表示开启，通俗地说，如果要求高实时性，有数据发送时就马上发送，就关闭，如果需要减少发送次数减少网络交互，就开启。
               // .childOption(ChannelOption.TCP_NODELAY, true)
                //option() 方法
                // 表示系统用于临时存放已完成三次握手的请求的队列的最大长度，如果连接建立频繁，服务器处理创建新连接较慢，可以适当调大这个参数
                //.option(ChannelOption.SO_BACKLOG, 1024)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {

                    }
                });
        bind(bootstrap, 1000);

    }

    private static void bind(final ServerBootstrap serverBootstrap, final int port) {
        serverBootstrap.bind(port).addListener(future -> {
            if (future.isSuccess()) {
                System.out.println("端口[" + port + "]绑定成功!");
            } else {
                System.err.println("端口[" + port + "]绑定失败!");
                bind(serverBootstrap, port + 1);
            }
        });
    }

}